type Listener = {
    id: string;
    callback: (...params: any[]) => void;
    args: unknown[];
};

let eventNum = 0;
export class EventBusClass {
    /**
     * 事件数组
     */
    private listeners: { [p: string]: Array<Listener> } = {};
    /**
     * 监听事件
     */
    public on(...params: any[]) {
        const type = params[0];
        const callback = params[1];
        const id = `${type}_${eventNum}`;
        let args = [];
        const numOfArgs = params.length;
        for (let i = 0; i < numOfArgs; i++) {
            args.push(params[i]);
        }
        args = args.length > 3 ? args.splice(3, args.length - 1) : [];
        if (typeof this.listeners[type] != 'undefined') {
            this.listeners[type].push({
                id: id,
                callback: callback,
                args: args,
            });
        } else {
            this.listeners[type] = [
                {
                    id: id,
                    callback: callback,
                    args: args,
                },
            ];
        }
        eventNum++;
        return id;
    }
    /**
     * 删除事件
     */
    public off(type: string, id: string) {
        if (typeof this.listeners[type] != 'undefined') {
            const numOfCallbacks = this.listeners[type].length;
            const newArray = [];
            for (let i = 0; i < numOfCallbacks; i++) {
                const listener = this.listeners[type][i];
                if (listener.id != id) {
                    newArray.push(listener);
                }
            }
            this.listeners[type] = newArray;
        }
    }
    /**
     * 判断事件是否存在
     */
    public has(type: string, id: string) {
        if (typeof this.listeners[type] != 'undefined' && id) {
            const numOfCallbacks = this.listeners[type].length;
            for (let i = 0; i < numOfCallbacks; i++) {
                const listener = this.listeners[type][i];
                if (listener.id == id) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * 发布事件
     */
    public emit(...params: any[]) {
        const type = params[0];
        if (!type) return;
        const arges = [];
        for (let index = 1; index < params.length; index++) {
            const element = params[index];
            arges.push(element);
        }

        if (typeof this.listeners[type] != 'undefined') {
            const listeners = this.listeners[type].slice();
            const numOfCallbacks = listeners.length;
            for (let i = 0; i < numOfCallbacks; i++) {
                const listener = listeners[i];
                if (listener && listener.callback != null) {
                    listener.callback(...arges, listener.args);
                }
            }
        }
    }
}

export const EventBus: EventBusClass = new EventBusClass();
